package com.kxmall.order.biz;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kxmall.common.enums.OrderStatusType;
import com.kxmall.common.enums.RiderOrderStatusType;
import com.kxmall.common.exception.ServiceException;
import com.kxmall.common.utils.redis.RedisUtils;
import com.kxmall.executor.GlobalExecutor;
import com.kxmall.notify.AdminNotifyBizService;
import com.kxmall.order.domain.KxStoreOrder;
import com.kxmall.order.domain.bo.OrderMessageBO;
import com.kxmall.order.domain.bo.RiderMessageBO;
import com.kxmall.order.domain.bo.RiderProductBO;
import com.kxmall.print.AdminPrintBizService;
import com.kxmall.rider.domain.KxRiderItem;
import com.kxmall.rider.domain.KxRiderOrder;
import com.kxmall.rider.mapper.KxRiderItemMapper;
import com.kxmall.rider.mapper.KxRiderOrderMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * Created by admin on 2019/7/10.
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class OrderRiderBizService {

    private static final Logger logger = LoggerFactory.getLogger(OrderRiderBizService.class);

    private static final Integer RIDER_ORDER_LOCK_WAITING_TIME = 30;

    private static final String RIDER_ORDER_STATUS_LOCK = "RIDER_ORDER_STATUS_LOCK";


    @Resource
    private KxRiderItemMapper riderSpuMapper;

    @Resource
    private KxRiderOrderMapper riderOrderMapper;

    @Resource
    private OrderBizService orderBizService;

    @Autowired
    private AdminNotifyBizService adminNotifyBizService;


    @Transactional(rollbackFor = Exception.class)
    public Boolean comsumerOderMessageBusiness(OrderMessageBO orderMessageBO) {
        if (orderMessageBO != null) {
            String orderNo = orderMessageBO.getOrderNo();
            Lock lock = RedisUtils.lock(RIDER_ORDER_STATUS_LOCK + orderNo);
            try {
                boolean isLocked = lock.tryLock(RIDER_ORDER_LOCK_WAITING_TIME, TimeUnit.SECONDS);
                if (isLocked) {
                    if (StringUtils.isEmpty(orderNo)) {
                        throw new ServiceException("配送订单信息缺少");
                    }
                    // 检查订单是否已经被分配过，如果已经分配，这个改变已分配的状态为‘已经被更改配送’
                    QueryWrapper<KxRiderOrder> wrapper = new QueryWrapper<>();
                    wrapper.eq("order_no", orderNo);
                    wrapper.notIn("status", RiderOrderStatusType.COMPLETED.getCode(), RiderOrderStatusType.RIDERERROR.getCode());
                    List<KxRiderOrder> riderOrderDOList = riderOrderMapper.selectList(wrapper);
                    if (riderOrderDOList != null && riderOrderDOList.size() > 0 && !riderOrderDOList.get(0).getRiderId().equals(orderMessageBO.getRiderId())) {
                        // 订单重新分配了配送员，修改就得订单状态；
                        KxRiderOrder riderOrderDO = riderOrderDOList.get(0);
                        riderOrderDO.setUpdateTime(new Date());
                        riderOrderDO.setStatus(RiderOrderStatusType.RIDERERROR.getCode());
                        riderOrderMapper.updateById(riderOrderDO);
                        // 重新分配的记录
                        return persistenceOrderRiderMessage(orderMessageBO);
                    } else if (riderOrderDOList != null && riderOrderDOList.size() > 0 && riderOrderDOList.get(0).getRiderId().equals(orderMessageBO.getRiderId())) {
                        // 还是原来的订单消息，不做处理
                        // TODO 可能修改了订单信息也要更新
                        return true;
                    } else {
                        // 新的订单配送
                        return persistenceOrderRiderMessage(orderMessageBO);
                    }
                } else {
                    throw new ServiceException("配送订单系统繁忙~");
                }
            } catch (Exception e) {
                logger.error("[配送订单信息] 异常", e);
                throw new ServiceException("配送订单系统未知异常");
            } finally {
                lock.unlock();
            }
        }
        return false;
    }

    private Boolean persistenceOrderRiderMessage(OrderMessageBO orderMessageBO) {
        KxRiderOrder riderOrderDO = new KxRiderOrder();
        BeanUtils.copyProperties(orderMessageBO, riderOrderDO);
        String payChannel = orderMessageBO.getPayChannel();
        riderOrderDO.setPayChannel(("WX".equals(payChannel) ? "微信" : payChannel));
        Date nowDate = new Date();
        riderOrderDO.setUpdateTime(nowDate);
        riderOrderDO.setCreateTime(nowDate);
        riderOrderDO.setStatus(RiderOrderStatusType.WAITING.getCode());
        if (riderOrderMapper.insert(riderOrderDO) > 0) {
            List<RiderProductBO> riderSpuBOList = orderMessageBO.getRiderSpuBOList();
            if (riderSpuBOList != null && riderSpuBOList.size() > 0) {
                KxRiderItem riderSpuDO;
                Long riderOrderDOId = riderOrderDO.getId();
                List<KxRiderItem> riderSpuDOList = new ArrayList<>();
                for (RiderProductBO riderSpuBO : riderSpuBOList) {
                    riderSpuDO = new KxRiderItem();
                    BeanUtils.copyProperties(riderSpuBO, riderSpuDO);
                    riderSpuDO.setRiderOrderId(riderOrderDOId);
                    riderSpuDOList.add(riderSpuDO);
                }
                riderSpuMapper.insertBatch(riderSpuDOList);
            }
            //发送消息
            this.sendRiderOrder(orderMessageBO);
            return true;
        }
        throw new ServiceException("配送订单消息保存失败");
    }

    /**
     * 发送订单消息给客户
     *
     * @param orderMessageBO
     */
    private void sendRiderOrder(OrderMessageBO orderMessageBO) {
        GlobalExecutor.execute(() -> {
            adminNotifyBizService.newRiderOrder(orderMessageBO);
        });
    }


    /**
     * 通知订单的配送信息
     *
     * @param orderNo              订单编号
     * @param riderOrderStatusType 配送状态
     * @param riderId              配送员主键ID
     * @param errorMsg             配送异常【如果有】
     * @return 是否成功
     * @throws ServiceException
     */
    public Boolean sendRiderMessageBusiness(String orderNo, RiderOrderStatusType riderOrderStatusType, Long riderId, String errorMsg) throws ServiceException {
        if (!StringUtils.isEmpty(orderNo) && riderOrderStatusType != null) {
            RiderMessageBO riderMessageBO = new RiderMessageBO();
            riderMessageBO.setOrderNo(orderNo);
            riderMessageBO.setRiderId(riderId);
            riderMessageBO.setErrorMsg(errorMsg);
            riderMessageBO.setOrderRiderStatus(riderOrderStatusType.getCode());
            orderRiderMeaageInPut(riderMessageBO);
            return true;
        }
        return false;
    }


    private void orderRiderMeaageInPut(RiderMessageBO riderMessageBO) {
        try {
            if (riderMessageBO != null) {
                switch (Objects.requireNonNull(RiderOrderStatusType.getBycode(riderMessageBO.getOrderRiderStatus()))) {
                    case DISPENSE:
                        // 1.订单配送
                        orderBizService.updateOrderStatus(riderMessageBO.getOrderNo(), OrderStatusType.WAIT_CONFIRM.getCode());
                        break;
                    case TIMEOUT:
                        // 2.订单配送超时
                        orderBizService.updateOrderStatus(riderMessageBO.getOrderNo(), OrderStatusType.TIME_OUT.getCode());
                        riderOrderMapper.updateRiderOrderStatus(riderMessageBO.getOrderNo(), RiderOrderStatusType.TIMEOUT.getCode(), false);
                        break;
                    case ABNORMAL:
                        // 3.订单配送异常
                        KxStoreOrder updateOrderDO = KxStoreOrder.builder().build();
                        updateOrderDO.setExceptionReason(riderMessageBO.getErrorMsg());
                        updateOrderDO.setStatus(OrderStatusType.TRANS_ABNORMAL.getCode());
                        orderBizService.updateOrder(riderMessageBO.getOrderNo(), updateOrderDO);
                        break;
                    case COMPLETED:
                        // 4.订单配送完成 -- 进入待评价
                        orderBizService.updateOrderStatus(riderMessageBO.getOrderNo(), OrderStatusType.WAIT_APPRAISE.getCode());
                        break;
                    default:
                        throw new ServiceException("配送订单消息保存失败");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.info(e.getMessage());
        }
        logger.info("【*** 订单配送消息结束,状态：{} ***】", (riderMessageBO != null) ? "success" : "fail");
    }
}
